<template>
  <div>
    <el-form ref="ruleForm" size="small" class="form-wrapper" :model="form" v-bind="$attrs" v-on="$listeners">
      <template v-if="!type">
        <div v-if="showHeader" class="form__header-wrapper">
          <el-row type="flex" :gutter="gutter">
            <div v-if="showOrderNum" class="serial-num">
              <!-- <div class="cell">序号</div> -->
            </div>
            <el-col v-for="item in formArray" :key="item.key" :span="item.span">
              <div class="cell">{{ item.label }}</div>
            </el-col>
          </el-row>
        </div>
        <div class="form__body-wrapper">
          <el-row v-for="(row, $index) in form.list" :key="$index" type="flex" :gutter="gutter">
            <div v-if="showOrderNum" class="serial-num">
              <div class="cell">{{ $index + 1 }}</div>
            </div>
            <el-col v-for="col in formArray" :key="col.key" :span="col.span">
              <template v-if="col.key === 'action'">
                <div class="buttons">
                  <el-button size="small" type="text" class="del-button" @click="deleteData($index)"> 删除 </el-button>
                </div>
              </template>
              <template v-else>
                <el-form-item :label-width="col.labelWidth" :prop="`list.${$index}.${col.key}`" :rules="col.rules">
                  <!-- custom 自定义 -->
                  <slot v-if="col.type === 'custom'" :name="col.key" :formData="row" :item="col"> </slot>
                  <template v-else>
                    <Item :form-data="row" :item="col" @change-value="val => handleDataChange(val, col.key, $index)" />
                  </template>
                </el-form-item>
              </template>
            </el-col>
          </el-row>
        </div>
      </template>
      <template v-else-if="type === 'card'">
        <div v-for="(row, $index) in form.list" :key="$index" class="card-list-item">
          <div class="form__header-wrapper">
            <div class="form__header-title">
              {{ title + ($index + 1) }}
            </div>
            <div class="buttons">
              <el-button size="small" type="text" class="del-button" @click="deleteData($index)"> 删除 </el-button>
            </div>
          </div>
          <div class="form__body-wrapper">
            <el-row :gutter="gutter">
              <template v-for="col in formArray">
                <el-col v-if="showItem(row, $index, col)" :key="col.key" :span="col.span">
                  <el-form-item
                    :label-width="col.labelWidth"
                    :label="col.label"
                    :prop="`list.${$index}.${col.key}`"
                    :rules="col.rules"
                  >
                    <!-- custom 自定义 -->
                    <slot v-if="col.type === 'custom'" :name="col.key" :formData="row" :item="col"> </slot>
                    <template v-else>
                      <Item
                        :form-data="row"
                        :item="col"
                        @change-value="val => handleDataChange(val, col.key, $index)"
                      />
                    </template>
                  </el-form-item>
                </el-col>
              </template>
            </el-row>
          </div>
        </div>
      </template>
    </el-form>
    <Footer :title="`添加${title}`" @add="addData" />
  </div>
</template>

<script>
import Item from './Item.vue'
import Footer from './Footer.vue'
// 动态表单
// @group Form
export default {
  name: 'DynamicForm',
  components: {
    Item,
    Footer
  },
  props: {
    type: {
      type: String,
      // ''|card
      default: ''
    },
    formList: {
      type: Array,
      default: () => []
    },
    rowKey: {
      type: String,
      default: 'id'
    },
    showOrderNum: {
      type: Boolean,
      default: false
    },
    gutter: {
      type: Number,
      default: 16
    },
    // 显示头部
    showHeader: {
      type: Boolean,
      default: true
    },
    // 表单项标题
    title: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      formArray: [],
      form: {
        list: []
      }
    }
  },
  watch: {
    formList: {
      handler(arr) {
        this.initFieldsList(arr)
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    // 初始化表单字段列表
    initFieldsList(arr) {
      const list = []
      arr.forEach(v => {
        const item = { ...v }
        if (!item.bind) item.bind = {}
        if (!item.on) item.on = {}
        if (!item.on.keyupNative) item.on.keyupNative = new Function()
        list.push(item)
      })
      this.formArray = list
    },
    // 表单项显示隐藏判断
    showItem(data, index, col) {
      return typeof col.hidden === 'function' ? !col.hidden(data, index) : !col.hidden
    },
    // @vuese
    // 获取数据
    getData() {
      return this.form.list
    },
    // @vuese
    // 回显数据
    // @arg Array
    setData(arr) {
      if (!arr || !arr.length) {
        this.form.list = []
        return
      }
      const list = arr.map(rowItem => ({
        ...rowItem
      }))
      Object.assign(this.form, { list })
      this.$nextTick(() => {
        this.$refs.ruleForm && this.$refs.ruleForm.clearValidate()
      })
    },
    // @vuese
    // 添加数据
    // @arg row
    addData(row = {}) {
      const formItem = this.formList
        .filter(v => v.key !== 'action')
        .reduce(
          (r, c) => ({
            ...r,
            [c.key]: c.defaultValue || ''
          }),
          {}
        )
      const obj = {
        ...formItem,
        ...row
      }
      obj[this.rowKey] = row[this.rowKey] || Date.now()
      this.form.list.push(obj)
    },
    // @vuese
    // 删除数据
    // @arg index
    deleteData(idx) {
      this.form.list.splice(idx, 1)
      this.$refs.ruleForm.fields.forEach(n => {
        if (n.key && n.key.split('.')[1] === idx) {
          n.clearValidate()
        }
      })
    },
    // 校验表单
    validate(...args) {
      return this.$refs.ruleForm.validate(...args)
    },
    // 对整个表单进行重置，将所有字段值重置为初始值并移除校验结果
    resetFields(...args) {
      return this.$refs.ruleForm.resetFields(...args)
    },
    handleDataChange(value, key, index) {
      this.$set(this.form.list[index], key, value)
    }
  }
}
</script>

<style lang='scss' scoped>
.form__header-wrapper,
.form__body-wrapper {
  // 序号样式
  .serial-num {
    min-width: 28px;
  }
  .del-button {
    color: #F5222D;
  }
}
.form__header-wrapper {
  margin-bottom: 10px;
  font-family: 'PingFang SC Bold';
  font-weight: bold;
  font-size: 14px;
  line-height: 22px;
  text-align: left;
  color: #8590a6;
}
.form__body-wrapper {
  // 序号样式
  .serial-num {
    margin-bottom: 18px;
    display: flex;
    align-items: center;
    .cell {
      width: 20px;
      height: 20px;
      line-height: 20px;
      background: rgba(133, 144, 166, 0.1);
      border: 1px solid #e4e6e9;
      border-radius: 50%;
      text-align: center;
      font-weight: 400;
      font-size: 12px;
      color: #333;
    }
  }
  .el-form-item {
    display: flex;
    ::v-deep {
      > .el-form-item__label {
        white-space: pre;
      }
      > .el-form-item__content {
        width: 1px;
        flex: 1;
        display: flex;
        align-items: center;
        margin-left: 0 !important;
        > {
          .el-input {
            flex: 1;
          }
          .el-select {
            flex: 1;
          }
          .el-cascader {
            flex: 1;
          }
        }
      }
    }
  }
}

.card-list-item {
  padding: 10px;
  .form__header-wrapper {
    position: relative;
    .form__header-title {
      font-weight: bold;
      font-size: 14px;
      color: #387afd;
    }
    .buttons {
      position: absolute;
      top: 0;
      right: 0;
    }
  }
}
.card-list-item:not(:nth-child(1)) {
  margin-top: 10px;
}
</style>
